import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:fate_blind_box/config/app_utils.dart';
import 'package:fate_blind_box/config/event_bus.dart';
import 'package:fate_blind_box/config/event_keys.dart';
import 'package:fate_blind_box/model/chat_friend_message_entity.dart';
import 'package:fate_blind_box/network/Api.dart';
import 'package:fate_blind_box/utils/default/common_config.dart';
import 'package:fate_blind_box/utils/loading.dart';
import 'package:fate_blind_box/utils/snack_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:im_flutter_sdk/im_flutter_sdk.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:video_player/video_player.dart';
import 'package:video_thumbnail/video_thumbnail.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart'
    hide ImageFormat;

import 'state.dart';

class ChatLogic extends GetxController with GetSingleTickerProviderStateMixin {
  final ChatState state = ChatState();

  @override
  void onInit() {
    // TODO: implement onInit
    super.onInit();
    if (Get.arguments != null) {
      state.nickName.value = Get.arguments['nickName'] ?? '';
      state.conversationId = Get.arguments['id'];
      state.avatarUrl.value = Get.arguments['avatarUrl'] ?? '';
    }
    if (CommonConfig.isHuaWeiPermission) {
      isOpenAudioPermission().then((value) {
        state.chatPageController.isShowAudioPermission = value;
        state.chatPageController.update([state.chatPageController.audioViewId]);
      });
    }
    addEventBus();
    initData();
    onRefresh();
    addEventHandler();
  }

  /// 发送消息成功消息监听
  addEventBus() {
    EventBus.instance.addListener(EventKeys.chatUpdateAudioMessage,
        (arg) async {
      if (arg.runtimeType == EMMessage) {
        EMMessage message = arg;
        Map<String, EMUserInfo> userInfo = await EMClient
            .getInstance.userInfoManager
            .fetchUserInfoById([message.from ?? '']);
        state.userInfoList.insertAll(0, userInfo.values.toList().reversed);
        state.messageList.insert(0, message);
        state.messageList.refresh();
      }
    });
  }

  /// 初始化数据 - 获取环信用户信息
  initData() async {
    if (state.conversationId.isEmpty) return;
    EasyLoading.show();
    final res = await Api.getInstance().getUserInfo(state.conversationId);
    EasyLoading.dismiss();
    final data = res['data'];
    if (data != null) {
      state.model.value = ChatFriendMessageEntity.fromJson(data);
      state.model.refresh();
    } else {
      if (kDebugMode) {
        print('------获取用户异常---------------' + res['msg']);
      }
    }
  }

  /// 根据指定会话 ID 和会话类型获取会话对象。
  onRefresh() async {
    state.conversation ??=
        await EMClient.getInstance.chatManager.getConversation(
      state.conversationId,
      type: EMConversationType.Chat,
      createIfNeed: true,
    );
    state.messageList.clear();
    state.userInfoList.clear();

    /// 从本地数据库 获取消息列表
    List<EMMessage>? list = await state.conversation?.loadMessages(
      startMsgId: '',
      loadCount: 20,
      direction: EMSearchDirection.Up,
    );

    /// 判断是否有更多
    if (list != null && list.length == 20) {
      state.hasMore.value = true;
    } else {
      state.hasMore.value = false;
    }
    if (list == null) {
      return;
    }
    var teamp = <EMUserInfo>[];
    for (int i = 0; i < list.length; i++) {
      int index = teamp.indexWhere((element) => element.userId == list[i].from);
      if (index == -1) {
        Map<String, EMUserInfo> userInfo = await EMClient
            .getInstance.userInfoManager
            .fetchUserInfoById([list[i].from ?? '']);
        teamp.add(userInfo.values.first);
      } else {
        teamp.add(teamp[index]);
      }
    }
    state.userInfoList.insertAll(0, teamp.reversed);
    state.messageList.insertAll(0, list.reversed);
    state.messageList.refresh();
  }

  onLoading() async {
    /// 从本地数据库 获取消息列表
    List<EMMessage>? list = await state.conversation?.loadMessages(
      startMsgId: state.messageList.last.msgId,
      loadCount: 20,
      direction: EMSearchDirection.Up,
    );
    state.refreshController.loadComplete();
    if (list != null && list.length == 20) {
      state.hasMore.value = true;
    } else {
      state.hasMore.value = false;
    }
    if (list == null) {
      return;
    }
    var teamp = <EMUserInfo>[];
    for (int i = 0; i < list.length; i++) {
      int index = state.userInfoList
          .indexWhere((element) => element.userId == list[i].from);
      if (index != -1) {
        teamp.add(state.userInfoList[index]);
      }
    }
    state.userInfoList.addAll(teamp.reversed);
    state.messageList.addAll(list.reversed);
    state.messageList.refresh();
  }

  /// 根据会话id 获取当前会话
  getConversation({required List<EMMessage> message}) async {
    for (int i = 0; i < message.length; i++) {
      if (message[i].conversationId == state.conversationId) {
        Map<String, EMUserInfo> userInfo = await EMClient
            .getInstance.userInfoManager
            .fetchUserInfoById([message[i].from ?? '']);
        state.userInfoList.insert(0, userInfo.values.first);
        state.messageList.insert(0, message[i]);
        state.messageList.refresh();
        // 将当前消息标记为已读
        await state.conversation?.markMessageAsRead(message[i].msgId);
      }
    }
  }

  /// 根据消息Id 检查消息列表中是否有当前消息
  EMMessage? getCurrentMessage(String msgId) {
    return state.messageList.firstWhere((element) => element.msgId == msgId);
  }

  /// 根据消息id 获取当前消息-为了替换本地消息
  /// msgId 旧消息id
  /// message  新消息
  /// 然后用新消息去替换旧消息，然后刷新页面即可
  replaceMessage({required String msgId, required EMMessage message}) async {
    final index =
        state.messageList.indexWhere((element) => element.msgId == msgId);
    if (index != -1) {
      state.messageList[index] = message;
      state.messageList.refresh();
    }
  }

  /// 添加环信消息监听
  addEventHandler() {
    /// 添加消息接收器监听
    EMClient.getInstance.chatManager.addEventHandler(
      state.tag,
      EMChatEventHandler(
        onMessagesReceived: (messages) async {
          getConversation(message: messages);
        },
      ),
    );

    EMClient.getInstance.chatManager.addMessageEvent(
      state.tag,
      ChatMessageEvent(
        // 收到成功回调之后，可以对发送的消息进行更新处理，或者其他操作。
        onSuccess: (msgId, msg) {
          log('消息发送成功');
          replaceMessage(msgId: msgId, message: msg);
        },
        // 收到回调之后，可以将发送的消息状态进行更新，或者进行其他操作。
        onError: (msgId, msg, error) {
          log('消息发送成功:${error.description}');
        },
        // 对于附件类型的消息，如图片，语音，文件，视频类型，上传或下载文件时会收到相应的进度值，表示附件的上传或者下载进度。
        onProgress: (msgId, progress) {
          log('消息发送进度$progress%');
          EMMessage? message = getCurrentMessage(msgId);
          if (message != null) {
            message.attributes = {'progress': progress};
            state.messageList.refresh();
          }
        },
      ),
    );
  }

  /// 收键盘
  void onFocusChange() {
    state.keyboardVisible.value = state.focusNode.hasFocus;
  }

  Future<bool> isOpenAudioPermission() async {
    var status = await Permission.microphone.status;
    if (status.isGranted) {
      return false;
    }
    return true;
  }

  void validateInput(String test) {
    state.canSend.value = test.isNotEmpty;
    state.centext = test;
  }

  onBackspacePressed() {
    state.canSend.value =
        state.messController.text.characters.toString().isNotEmpty;
    state.centext = state.messController.text.characters.toString();
  }

// 获取自定义键盘 高度
  double get customKeyBoardHeight {
    if (state.emojiShowing.value) {
      return 230;
    }
    return 0;
  }

  /// 最新一条消息
  EMMessage? get lastMessage {
    if (state.messageList.isNotEmpty) {
      return state.messageList.last;
    } else {
      return null;
    }
  }

  /// 检查相机权限
  checkPermissionStatus() async {
    PermissionStatus cameraStatus = await Permission.camera.status;
    if (!cameraStatus.isGranted) {
      // 相机权限未授权
      if (await Permission.camera.request().isGranted) {
        // 用户已授权相机权限
      } else {
        // 用户拒绝了相机权限
        await openAppSettings();
      }
    } else {
      // 相机权限已授权
      if (!kIsWeb) {
        loading(() async {
          final picker = ImagePicker();
          final pickerFile =
              await picker.pickImage(source: ImageSource.gallery);
          if (pickerFile != null) {
            //裁剪后图片的路径
            String filepath = pickerFile.path;
            if (filepath.toString().isEmpty) return;
            EMMessage message = EMMessage.createImageSendMessage(
              targetId: state.conversationId,
              filePath: filepath.toString(),
              chatType: ChatType.Chat,
            );
            EMClient.getInstance.chatManager.sendMessage(message);
          }
        });
      }
    }
  }

  /// 根据权限跳转
  selectPhoto(String type) {
    if (type == '图片') {
      _pickImageFromPhoto();
    } else {
      _pickVideoFromPhoto();
    }
  }

  /// 从相册选择视频
  _pickVideoFromPhoto() async {
    FilterOptionGroup optionGroup = FilterOptionGroup()
      ..containsLivePhotos = false;
    final List<AssetEntity>? entities = await AssetPicker.pickAssets(
        Get.context!,
        pickerConfig: AssetPickerConfig(
            maxAssets: 1,
            requestType: RequestType.video,
            filterOptions: optionGroup));
    if (entities == null) return;
    for (AssetEntity entity in entities) {
      File? file = await entity.file;
      if (file == null) return;
      VideoPlayerController controller = VideoPlayerController.file(file);
      controller.initialize().then((value) async {
        var urlPath = await VideoThumbnail.thumbnailFile(
          video: file.path,
          imageFormat: ImageFormat.PNG,
          maxWidth: 260,
          quality: 80,
        );
        if (urlPath == null) return;
        _createVideoMessage(controller, file, urlPath);
        // 释放资源
        controller.dispose();
      });
    }
  }

  /// 从相册选择照片
  _pickImageFromPhoto() async {
    final List<AssetEntity>? entity = await AssetPicker.pickAssets(Get.context!,
        pickerConfig: const AssetPickerConfig(
          maxAssets: 9,
          requestType: RequestType.image,
        ));
    if (entity == null) return;
    for (AssetEntity entity in entity) {
      File? imgFile = await entity.file;
      if (imgFile == null) return;
      final size = await AppUtils.getImageSize(imgFile);
      _sendImageMessage(
        imgFile.path,
        size.width,
        size.height,
      );
    }
  }

  /// 拍摄
  cameraAction(BuildContext context) async {
    final AssetEntity? entity = await CameraPicker.pickFromCamera(
      context,
      pickerConfig: const CameraPickerConfig(
          enableRecording: true,
          maximumRecordingDuration: Duration(seconds: 30)),
    );
    if (entity == null) return;
    File? imgFile = await entity.file;
    if (imgFile == null) return;
    if (entity.duration > 0) {
      VideoPlayerController controller = VideoPlayerController.file(imgFile);
      controller.initialize().then((value) async {
        var urlPath = await VideoThumbnail.thumbnailFile(
          video: imgFile.path,
          imageFormat: ImageFormat.PNG,
          maxWidth: 260,
          quality: 80,
        );
        if (urlPath == null) return;
        _createVideoMessage(controller, imgFile, urlPath);
        // 释放资源
        controller.dispose();
      });
    } else {
      if (imgFile == null) return;
      final size = await AppUtils.getImageSize(imgFile);
      _sendImageMessage(
        imgFile.path,
        size.width,
        size.height,
      );
    }
  }

  /// 创建视频消息
  _createVideoMessage(
      VideoPlayerController controller, File file, String urlPath) {
    EMMessage message = EMMessage.createVideoSendMessage(
      targetId: state.conversationId,
      filePath: file.path,
      duration: controller.value.duration.inSeconds,
      width: controller.value.size.width.toDouble(),
      height: controller.value.size.height.toDouble(),
      thumbnailLocalPath: urlPath,
      chatType: ChatType.Chat,
    );
    _sendVideoMessage(message);
  }

  /// 发送图片
  _sendImageMessage(String filePath, int width, int height) async {
    EMMessage message = EMMessage.createImageSendMessage(
      targetId: state.conversationId,
      filePath: filePath.toString(),
      width: width.toDouble(),
      height: height.toDouble(),
      chatType: ChatType.Chat,
    );
    bool status = await EMClient.getInstance.isConnected();
    if (status) {
      EMClient.getInstance.chatManager.sendMessage(message).then((value) {
        EventBus.instance
            .commit(eventName: EventKeys.chatUpdateAudioMessage, data: message);
      });
    } else {
      ThemeSnackBar.show(Get.context!, '已断线,请重新登陆~');
      FocusScope.of(Get.context!).unfocus();
    }
  }

  /// 发送消息
  _sendVideoMessage(EMMessage message) async {
    bool status = await EMClient.getInstance.isConnected();
    if (status) {
      EMClient.getInstance.chatManager.sendMessage(message).then((value) {
        EventBus.instance
            .commit(eventName: EventKeys.chatUpdateAudioMessage, data: message);
      });
    } else {
      ThemeSnackBar.show(Get.context!, '已断线,请重新登陆~');
      FocusScope.of(Get.context!).unfocus();
    }
  }

  @override
  void onClose() {
    // TODO: implement onClose
    super.onClose();
    EMClient.getInstance.chatManager.removeEventHandler(state.tag);
    EMClient.getInstance.chatManager.removeMessageEvent(state.tag);
    EventBus.instance
        .removeListener(eventName: EventKeys.chatUpdateAudioMessage);
    state.focusNode.removeListener(onFocusChange);
    state.focusNode.dispose();
    // 关闭播放器
    state.recorderModule.closeRecorder();
    state.playerModule.closePlayer();
    state.subscription?.cancel();
  }
}
